package com.bestcem.xm.member.grpc.service;

import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import com.bestcem.xm.member.grpc.service.param.project.*;
import com.bestcem.xm.member.grpc.v1.common.*;
import com.bestcem.xm.member.grpc.v1.services.*;
import com.bestcem.xm.member.service.ProjectService;
import com.bestcem.xm.member.service.dto.ProjectDto;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @description 联系人项目grpc接口
 * @date 2021/7/20
 */
@GrpcService
public class MemberProjectGrpcService extends ProjectServiceGrpc.ProjectServiceImplBase {

    private final ProjectService projectService;

    @Autowired
    public MemberProjectGrpcService(ProjectService projectService){
        this.projectService = projectService;
    }

    @Override
    public void validateName(ValidateNameRequest request, StreamObserver<ValidateResponse> responseObserver) {
        ValidateResponse.Builder builder = ValidateResponse.newBuilder();

        // 类型转化
        ValidateNameParam validateNameParam = new ValidateNameParam();
        validateNameParam.setOrgId(request.getOrgId());
        validateNameParam.setProjectName(request.getName());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(validateNameParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<Boolean> result = projectService.validateName(validateNameParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setValid(result.getData());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getProject(GetProjectRequest request, StreamObserver<GetProjectResponse> responseObserver) {
        GetProjectResponse.Builder builder = GetProjectResponse.newBuilder();

        //
        GetProjectParam getProjectParam = new GetProjectParam();
        getProjectParam.setOrgId(request.getOrgId());
        getProjectParam.setId(request.getId());
        getProjectParam.setUserId(request.getUserId());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(getProjectParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<ProjectDto> result = projectService.getProject(getProjectParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        Project project = this.convertFrom(result.getData());
        builder.setStatus(RpcStatusResult.success());
        builder.setProject(project);
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getProjectById(GetProjectByIdRequest request, StreamObserver<GetProjectResponse> responseObserver) {
        GetProjectResponse.Builder builder = GetProjectResponse.newBuilder();

        ListProjectsParam param = new ListProjectsParam();
        param.setIds(Collections.singletonList(request.getId()));

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            // 特殊grpc接口，不校验orgId
            if(violations.size() > 1 || !"企业标识为空".equals(violation.getMessage())){
                builder.setStatus(RpcStatusResult.error(violation.getMessage()));
                responseObserver.onNext(builder.build());
                responseObserver.onCompleted();
                return;
            }
        }

        ServiceResult<List<ProjectDto>> result = projectService.listProjects(param);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        List<ProjectDto> projectDtos = result.getData();
        if(!CollectionUtils.isEmpty(projectDtos)){
            List<Project> projects = projectDtos.stream().map(this::convertFrom).collect(Collectors.toList());
            builder.setProject(projects.stream().findAny().get());
        }
        builder.setStatus(RpcStatusResult.success());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void listProjectsByIds(ListProjectsByIdsRequest request, StreamObserver<ListProjectsByIdsResponse> responseObserver) {
        ListProjectsByIdsResponse.Builder builder = ListProjectsByIdsResponse.newBuilder();

        ListProjectsParam param = new ListProjectsParam();
        param.setIds(request.getIdsList());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            // 特殊grpc接口，不校验orgId
            if(violations.size() != 1 || !"企业标识为空".equals(violation.getMessage())){
                builder.setStatus(RpcStatusResult.error(violation.getMessage()));
                responseObserver.onNext(builder.build());
                responseObserver.onCompleted();
                return;
            }
        }

        ServiceResult<List<ProjectDto>> result = projectService.listProjects(param);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        List<ProjectDto> projectDtos = result.getData();
        if(!CollectionUtils.isEmpty(projectDtos)){
            List<Project> projects = projectDtos.stream().map(this::convertFrom).collect(Collectors.toList());
            builder.addAllProjects(projects);
        }
        builder.setStatus(RpcStatusResult.success());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

//    @Override
//    public void listProject(ListProjectsRequest request, StreamObserver<ListProjectsResponse> responseObserver) {
//        ListProjectsResponse.Builder builder = ListProjectsResponse.newBuilder();
//
//        ListProjectsParam listProjectsParam = new ListProjectsParam();
//        listProjectsParam.setOrgId(request.getOrgId());
//        listProjectsParam.setMemberId(request.getMemberId());
//
//        // 参数校验
//        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(listProjectsParam);
//        if (!CollectionUtils.isEmpty(violations)) {
//            ConstraintViolation<Object> violation = violations.iterator().next();
//            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
//            responseObserver.onNext(builder.build());
//            responseObserver.onCompleted();
//            return;
//        }
//
//        ServiceResult<List<ProjectDto>> result = projectService.listProjects(listProjectsParam);
//        if(!result.isSuccess()){
//            builder.setStatus(RpcStatusResult.error(result.getMsg()));
//            responseObserver.onNext(builder.build());
//            responseObserver.onCompleted();
//            return;
//        }
//
//        List<Project> projects = result.getData().stream().map(p -> this.newProjectBuilder(p).build()).collect(Collectors.toList());
//        builder.setStatus(RpcStatusResult.success());
//        builder.addAllProjects(projects);
//        responseObserver.onNext(builder.build());
//        responseObserver.onCompleted();
//    }

    @Override
    public void createProject(CreateProjectRequest request, StreamObserver<CreateResponse> responseObserver) {
        CreateResponse.Builder builder = CreateResponse.newBuilder();

        CreateProjectParam createProjectParam = new CreateProjectParam();
        BeanUtils.copyProperties(request.getProject(), createProjectParam);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(createProjectParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<String> result = projectService.createProject(createProjectParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setId(result.getData());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void updateProject(UpdateProjectRequest request, StreamObserver<UpdateResponse> responseObserver) {
        UpdateResponse.Builder builder = UpdateResponse.newBuilder();

        UpdateProjectParam updateProjectParam = new UpdateProjectParam();
        BeanUtils.copyProperties(request.getProject(), updateProjectParam);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(updateProjectParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<String> result = projectService.updateProject(updateProjectParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setId(result.getData());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void batchDeleteProjects(BatchDeleteProjectsRequest request, StreamObserver<BatchDeleteResponse> responseObserver) {
        BatchDeleteResponse.Builder builder = BatchDeleteResponse.newBuilder();

        BatchDeleteProjectParam batchDeleteProjectParam = new BatchDeleteProjectParam();
        batchDeleteProjectParam.setOrgId(request.getOrgId());
        batchDeleteProjectParam.setIds(request.getIdsList());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(batchDeleteProjectParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<Integer> result = projectService.batchDeleteByIds(batchDeleteProjectParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setDeleteCount(result.getData().intValue());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    private Project convertFrom(ProjectDto projectDto){
        Project.Builder builder = Project.newBuilder();
        if(projectDto.getId() != null){
            builder.setId(projectDto.getId());
        }
        if(projectDto.getOrgId() != null){
            builder.setOrgId(projectDto.getOrgId());
        }
        if(projectDto.getName() != null){
            builder.setName(projectDto.getName());
        }
        if(projectDto.getMemberId() != null){
            builder.setMemberId(projectDto.getMemberId());
        }
        if(projectDto.getCode() != null){
            builder.setCode(projectDto.getCode());
        }
        if(projectDto.getStatus() != null){
            builder.setStatus(projectDto.getStatus());
        }
        if(projectDto.getType() != null){
            builder.setType(projectDto.getType());
        }
        if(projectDto.getContractNo() != null){
            builder.setContractNo(projectDto.getContractNo());
        }
        if(projectDto.getContractObj() != null){
            builder.setContractObj(projectDto.getContractObj());
        }
        if(projectDto.getContractMoney() != null){
            builder.setContractMoney(projectDto.getContractMoney().intValue());
        }
        if(projectDto.getAccountManager() != null){
            builder.setAccountManager(projectDto.getAccountManager());
        }
        if(projectDto.getProjectManager() != null){
            builder.setProjectManager(projectDto.getProjectManager());
        }
        if(projectDto.getProjectManagerMobile() != null){
            builder.setManagerPhone(projectDto.getProjectManagerMobile());
        }
        if(projectDto.getProjectTime() != null){
            builder.setProjectTime(DateUtil.getTimestamp(projectDto.getProjectTime()));
        }
        if(projectDto.getProgramStartTime() != null){
            builder.setProgramStartTime(DateUtil.getTimestamp(projectDto.getProgramStartTime()));
        }
        if(projectDto.getActualStartTime() != null){
            builder.setActualStartTime(DateUtil.getTimestamp(projectDto.getActualStartTime()));
        }
        if(projectDto.getAcceptanceTime() != null){
            builder.setAcceptanceTime(DateUtil.getTimestamp(projectDto.getAcceptanceTime()));
        }
        if(projectDto.getEndTime() != null){
            builder.setEndTime(DateUtil.getTimestamp(projectDto.getEndTime()));
        }
        // fixme 添加扩展字段

        return builder.build();
    }
}

